﻿namespace WebPacker.Packs
{
	using System;
	using System.Collections;
	using System.Collections.Generic;

	public sealed class PackCollection : ICollection<IPack>
	{
		private readonly IDictionary<PackKey, IPack> packMap;

		public PackCollection()
		{
			this.packMap = new Dictionary<PackKey, IPack>();
		}

		public int Count
		{
			get { return packMap.Count; }
		}

		public bool IsReadOnly
		{
			get { return false; }
		}

		public void Add(IPack item)
		{
			if (item == null)
			{
				throw new ArgumentNullException("item");
			}

			packMap.Add(new PackKey(item.PackType, item.Name), item);
		}

		public void AddRange(IEnumerable<IPack> items)
		{
			if (items == null)
			{
				throw new ArgumentNullException("items");
			}

			foreach (var item in items)
			{
				Add(item);
			}
		}

		public bool TryGetItem(PackType packType, string packName, out IPack pack)
		{
			if (packName == null)
			{
				throw new ArgumentNullException("packName");
			}

			return packMap.TryGetValue(new PackKey(packType, packName), out pack);
		}

		public IPack GetItem(PackType packType, string packName)
		{
			IPack pack;

			if (!TryGetItem(packType, packName, out pack))
			{
				throw new ArgumentException(string.Format("Pack \"{0}\" for {1} isn't found.", packName, packType));
			}

			return pack;
		}

		public void Clear()
		{
			packMap.Clear();
		}

		public bool Contains(IPack item)
		{
			if (item == null)
			{
				throw new ArgumentNullException("item");
			}

			return packMap.Values.Contains(item);
		}

		public bool Contains(PackType packType, string packName)
		{
			if (packName == null)
			{
				throw new ArgumentNullException("packName");
			}

			return packMap.ContainsKey(new PackKey(packType, packName));
		}

		public void CopyTo(IPack[] array, int arrayIndex)
		{
			packMap.Values.CopyTo(array, arrayIndex);
		}

		public bool Remove(IPack item)
		{
			if (item == null)
			{
				throw new ArgumentNullException("item");
			}

			return packMap.Remove(new KeyValuePair<PackKey, IPack>(new PackKey(item.PackType, item.Name), item));
		}

		public bool Remove(PackType packType, string packName)
		{
			if (packName == null)
			{
				throw new ArgumentNullException("packName");
			}

			return packMap.Remove(new PackKey(packType, packName));
		}

		public IEnumerator<IPack> GetEnumerator()
		{
			var packs = new List<IPack>(packMap.Count);
			packs.AddRange(packMap.Values);
			return packs.GetEnumerator();
		}

		IEnumerator IEnumerable.GetEnumerator()
		{
			return GetEnumerator();
		}
	}
}
